package com.adou.service.impl;

import com.adou.common.dto.AddFieldDto;
import com.adou.common.dto.DataTypeDto;
import com.adou.common.dto.ParseHtmlDto;
import com.adou.common.dto.RunKeyFormDto;
import com.adou.common.mapper.*;
import com.adou.common.model.*;
import com.adou.common.util.StringUtil;
import com.adou.common.util.UtilPath;
import com.adou.service.FormModelService;
import com.adou.service.impl.base.BaseServiceImp;
import com.adou.shiro.token.TokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.*;

@Service("FormModelService")
public class FormModelServiceImp extends BaseServiceImp<DefForm> implements FormModelService {

    @Autowired
    private DefFormMapper dao;
    @Autowired
    private DefFieldMapper fielddao;
    @Autowired
    private RunKeyFormMapper keydao;
    @Autowired
    private RunDynXxxMapper dyndao;
    @Autowired
    private SearchLoginFormMapper logindao;

    /**
     * 删除数据引入mapper
     */
    @Autowired
    private FlowMainMapper flowMainMapper;
    @Autowired
    private FlowMainFileMapper flowMainFileMapper;
    @Autowired
    private FlowDirectionMapper flowDirectionMapper;
    @Autowired
    private FlowHistoryMapper flowHistoryMapper;
    @Autowired
    private WorkAttachMapper workAttachMapper;

    @Override
    @Transactional
    public int insertDefForm(DefForm defForm) {
        int res = 0;
        String formname = defForm.getCformname();
        int crttype = defForm.getIcrttype();
        String formdisplay = defForm.getCformdisplay();
        if(!StringUtil.isNotBlank(formname)){
            return 211;
        }
        if(!(crttype == 0 || crttype == 1)){
            return 212;
        }
        if(!StringUtil.isNotBlank(formdisplay)){
            return 213;
        }
        if(!(dao.count(defForm) == 0)){
            return 214;
        }
        defForm.setDdate(new Date());
        defForm.setBflag(false);
        defForm.setCcreator(TokenManager.getUserNameByKey());
        defForm.setIver(1);
        res = dao.insert(defForm);
        return res;
    }

    @Override
    @Transactional
    public int updateDefForm(DefForm defForm) {
        int res = 0;
        String formname = defForm.getCformname();
        int crttype = defForm.getIcrttype();
        String formdisplay = defForm.getCformdisplay();
        if(!StringUtil.isNotBlank(formname)){
            return 211;
        }
        if(!(crttype == 0 || crttype == 1)){
            return 212;
        }
        if(!StringUtil.isNotBlank(formdisplay)){
            return 213;
        }
        if(!(dao.count(defForm) == 0)){
            return 214;
        }
        DefForm o = new DefForm();
        o.setId(defForm.getId());
        List<DefForm> list = dao.find(o);
        //判断是否未发布
        if (list==null){
            return 215;
        }
        if(list.get(0).getBflag()){
            return 216;
        }
        //判断是否进行模型设计，模型设计后不允许更改创建表类型、表单英文名
        if (list.get(0).getIcrttype() == 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("database_Name", dyndao.getCurDataBaseName());
            map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
            String table_name = dyndao.isTargetTableExistInDB(map);
            if (table_name != null) {
                if (!list.get(0).getCformname().equals(formname)) {
                    return res;
                } else if (crttype != list.get(0).getIcrttype()) {
                    return res;
                }
            }
        } else if (list.get(0).getIcrttype() == 1) {
            DefField field = new DefField();
            field.setIformid(list.get(0).getId());
            if (fielddao.count(field) > 0) {
                if (!list.get(0).getCformname().equals(formname)) {
                    return res;
                } else if (crttype != list.get(0).getIcrttype()) {
                    return res;
                }
            }
        } else {
            return res;
        }
        res = dao.update(defForm);
        return res;
    }

    @Override
    @Transactional
    public int deleteDefForm(DefForm defForm) {
        int res = 0;
        List<DefForm> list = dao.find(defForm);

        //判断是否发布
        if(list==null){
            return 211;
        }
        if(list.get(0).getBflag()){
            return 212;
        }

        //判断创建表类型并进行相应删除操作
        if (list.get(0).getIcrttype() == 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("database_Name", dyndao.getCurDataBaseName());
            map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
            String table_name = dyndao.isTargetTableExistInDB(map);
            if (table_name != null) {
                dyndao.dropTable(list.get(0).getCformname() + list.get(0).getIver());
                logindao.deleteByFid(defForm.getId());
            }
            keydao.deleteByFormId(defForm.getId());
            res = dao.delete(defForm);
        } else if (list.get(0).getIcrttype() == 1) {
            fielddao.deleteFormid(defForm.getId());
            logindao.deleteByFid(defForm.getId());
            res = dao.delete(defForm);
        }
        return res;
    }

    @Override
    @Transactional
    public int deployDefForm(DefForm defForm) {
        int res = 0;
        List<DefForm> list = dao.find(defForm);

        //判断是否未发布
        if(list==null){
            return 211;
        }
        if(list.get(0).getBflag()){
            return 212;
        }

        if (list.get(0).getIcrttype() == 0) {
            //动态表
            Map<String, Object> map = new HashMap<>();
            map.put("database_Name", dyndao.getCurDataBaseName());
            map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
            String table_name = dyndao.isTargetTableExistInDB(map);
            if (table_name == null) {
                return res;
            }
        } else if (list.get(0).getIcrttype() == 1) {
            DefField field = new DefField();
            field.setIformid(list.get(0).getId());
            if (fielddao.count(field) == 0) {
                return res;
            }
        }
        defForm.setBflag(true);
        res = dao.updateFlag(defForm);
        return res;
    }

    @Override
    @Transactional
    public int cancelDefForm(DefForm defForm) {
        int res = 0;
        List<DefForm> list = dao.find(defForm);
        //判断是否已发布
        if(list==null){
            return 211;
        }
        if(!list.get(0).getBflag()){
            return 212;
        }
        if (list.get(0).getIcrttype() == 0) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("field_names", "id");
            map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
            map.put("iformid", list.get(0).getId());
            List<Map<String, Object>> resultMap = dyndao.findAll(map);
            if (resultMap == null || resultMap.size() == 0) {
                defForm.setBflag(false);
                res = dao.updateFlag(defForm);
            }
        } else if (list.get(0).getIcrttype() == 1) {
            RunKeyForm keyform = new RunKeyForm();
            keyform.setIformid(list.get(0).getId());
            if (keydao.count(keyform) == 0) {
                defForm.setBflag(false);
                res = dao.updateFlag(defForm);
            }
        }
        return res;
    }

    @Override
    @Transactional
    public int updateDesin(ParseHtmlDto parsedto) {
        int res = 0;
        DefForm defForm = new DefForm();
        defForm.setId(parsedto.getFormId());
        List<DefForm> list = dao.find(defForm);
        //判断是否未发布
        if (list != null && !list.get(0).getBflag()) {
            //判断是否有重复fieldname
            List<DataTypeDto> dtlist = parsedto.getDataType();
            if (dtlist == null || dtlist.size() == 0) {
                return 211;
            }

            for (int i = 0; i < dtlist.size(); i++) {
                for (int j = i + 1; j < dtlist.size(); j++) {
                    if (dtlist.get(i).getFieldname().equals(dtlist.get(j).getFieldname())) {
                        return 212;
                    }
                }
            }
            DefForm updateform = new DefForm();
            updateform.setId(parsedto.getFormId());
            updateform.setIfieldnum(parsedto.getFieldNum());
            updateform.setCoriginalhtml(parsedto.getOriginal());
            updateform.setCparsehtml(parsedto.getParse());
            dao.updateDesign(updateform);
            if (list.get(0).getIcrttype() == 0) {
                //动态表
                Map<String, Object> map = new HashMap<>();
                map.put("database_Name", dyndao.getCurDataBaseName());
                map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
                String table_name = dyndao.isTargetTableExistInDB(map);
                if (table_name != null) {
                    dyndao.dropTable(table_name);
                }
                map.clear();
                map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
                StringBuilder sql = new StringBuilder();
                sql.append("id BIGINT NOT NULL AUTO_INCREMENT,");
                for (DataTypeDto field : parsedto.getDataType()) {
                    sql.append(field.getFieldname());
                    sql.append(" ").append(fieldSQL(field)).append(",");
                }

                sql.append("iformId BIGINT NOT NULL,");
                sql.append("iflowId BIGINT,");
                sql.append("PRIMARY KEY (id)");
                map.put("table_field_defs", sql.toString());
                dyndao.createNewTable(map);

                List<RunKeyForm> runList = new LinkedList<>();
                for (DataTypeDto field : parsedto.getDataType()) {
                    RunKeyForm runKeyForm = new RunKeyForm();
                    runKeyForm.setCfieldname(field.getTitle());
                    runKeyForm.setCvalue(field.getFieldname());
                    runKeyForm.setIformid(parsedto.getFormId());
                    runList.add(runKeyForm);
                }
                keydao.deleteByFormId(parsedto.getFormId());
                keydao.butchInsert(runList);
                res = 1;
            } else if (list.get(0).getIcrttype() == 1) {
                //键值对
                fielddao.deleteFormid(list.get(0).getId());
                for (DataTypeDto field : parsedto.getDataType()) {
                    DefField o = new DefField();
                    o.setIformid(list.get(0).getId());
                    o.setCfieldname(field.getFieldname());
                    o.setCfielddisplay(field.getTitle());
                    o.setCfieldtype(field.getType());
                    o.setCformname(list.get(0).getCformname() + list.get(0).getIver());
                    o.setCobjecttype(field.getPlugins());
                    fielddao.insert(o);
                }
                res = 1;
            }
        }
        return res;
    }

    @Override
    @Transactional
    public int upgradeDesin(ParseHtmlDto parsedto) {
        int res = 0;
        DefForm defForm = new DefForm();
        defForm.setId(parsedto.getFormId());
        List<DefForm> list = dao.find(defForm);
        //判断是否已发布
        if (list != null && list.get(0).getBflag()) {
            //判断是否有重复fieldname
            List<DataTypeDto> dtlist = parsedto.getDataType();
            if (dtlist == null || dtlist.size() == 0) {
                return 211;
            }

            for (int i = 0; i < dtlist.size(); i++) {
                for (int j = i + 1; j < dtlist.size(); j++) {
                    if (dtlist.get(i).getFieldname().equals(dtlist.get(j).getFieldname())) {
                        return 212;
                    }
                }
            }
            DefForm newform = new DefForm();
            newform.setDdate(new Date());
            newform.setBflag(true);
            newform.setCcreator(TokenManager.getUserNameByKey());
            newform.setIver(dao.selectMaxVerByFormname(list.get(0).getCformname()) + 1);
            newform.setCformdisplay(list.get(0).getCformdisplay() + "v" + newform.getIver());
            newform.setCformname(list.get(0).getCformname());
            newform.setCformtype(list.get(0).getCformtype());
            newform.setCoriginalhtml(parsedto.getOriginal());
            newform.setCparsehtml(parsedto.getParse());
            newform.setIcrttype(list.get(0).getIcrttype());
            newform.setIfieldnum(parsedto.getFieldNum());
            dao.insert(newform);
            if (list.get(0).getIcrttype() == 0) {
                //动态表
                Map<String, Object> map = new HashMap<>();
                map.put("database_Name", dyndao.getCurDataBaseName());
                map.put("table_name", newform.getCformname() + newform.getIver());
                String table_name = dyndao.isTargetTableExistInDB(map);
                if (table_name != null) {
                    dyndao.dropTable(table_name);
                }
                map.clear();
                map.put("table_name", newform.getCformname() + newform.getIver());
                StringBuilder sql = new StringBuilder();
                sql.append("id BIGINT NOT NULL AUTO_INCREMENT,");
                for (DataTypeDto field : parsedto.getDataType()) {
                    sql.append(field.getFieldname());
                    sql.append(" ").append(fieldSQL(field)).append(",");
                }

                sql.append("iformId BIGINT NOT NULL,");
                sql.append("iflowId BIGINT,");
                sql.append("PRIMARY KEY (id)");
                map.put("table_field_defs", sql.toString());
                dyndao.createNewTable(map);

                /**
                 * 添加键值映射
                 */
                List<RunKeyForm> runList = new LinkedList<>();
                for (DataTypeDto field : parsedto.getDataType()) {
                    RunKeyForm runKeyForm = new RunKeyForm();
                    runKeyForm.setCfieldname(field.getTitle());
                    runKeyForm.setCvalue(field.getFieldname());
                    runKeyForm.setIformid(newform.getId());
                    runList.add(runKeyForm);
                }
                keydao.deleteByFormId(newform.getId());
                keydao.butchInsert(runList);

                res = 1;
            } else if (list.get(0).getIcrttype() == 1) {
                //键值对
                for (DataTypeDto field : parsedto.getDataType()) {
                    DefField o = new DefField();
                    o.setIformid(newform.getId());
                    o.setCfieldname(field.getFieldname());
                    o.setCfielddisplay(field.getTitle());
                    o.setCfieldtype(field.getType());
                    o.setCformname(newform.getCformname() + newform.getIver());
                    o.setCobjecttype(field.getPlugins());
                    fielddao.insert(o);
                }
                res = 1;
            }
        }
        return res;
    }

    @Override
    @Transactional
    public Map<String, Object> getFormContentByFlowId(Long flowId, Long formId, Long id) {
        Map<String, Object> resultMap = new HashMap<>();
        DefForm defForm = new DefForm();
        defForm.setId(formId);
        List<DefForm> list = dao.find(defForm);
        //判断是否已发布
        if (list != null && list.get(0).getBflag()) {
            if (list.get(0).getIcrttype() == 0) {
                Map<String, Object> map = new HashMap<>();
                map.put("field_names", "*");
                map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
                map.put("iformId", formId);
                map.put("iflowId", flowId);
                map.put("id", id);
                List<Map<String, Object>> dynMap = dyndao.findAll(map);
                resultMap.put("res", 1);
                Map<String, Object> data = new HashMap<>();
                data.put("formInfo", list.get(0));
                data.put("formValue", dynMap);
                resultMap.put("data", data);
            } else if (list.get(0).getIcrttype() == 1) {
                RunKeyForm keyForm = new RunKeyForm();
                keyForm.setIflowid(flowId);
                keyForm.setIformid(formId);
                List<RunKeyForm> keyList = keydao.find(keyForm);
                Map<String, Object> map = new HashMap<>();
                for (RunKeyForm key : keyList) {
                    map.put(key.getCfieldname(), key.getCvalue());
                }
                resultMap.put("res", 1);
                Map<String, Object> data = new HashMap<>();
                data.put("formInfo", list.get(0));
                data.put("formValue", map);
                resultMap.put("data", data);
            } else {
                resultMap.put("res", 0);
            }
        } else {
            resultMap.put("res", 0);
        }
        return resultMap;
    }

    @Override
    @Transactional
    public int setFormContentByFlowId(List<AddFieldDto> addList, Long flowId, Long formId, Long id) {
        int res = 0;
        //根据表单创建类型更新或插入对应字段值
        DefForm defForm = new DefForm();
        defForm.setId(formId);
        List<DefForm> list = dao.find(defForm);
        //判断是否已发布
        if (list != null && list.get(0).getBflag()) {
            if (list.get(0).getIcrttype() == 0) {
                Map<String, Object> map = new HashMap<>();
                map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
                if (id != null) {
                    String update_fields_value = "";
                    for (AddFieldDto field : addList) {
                        if (field.getType().equals("int") || field.getType().equals("float"))
                            update_fields_value +=  field.getFieldname() + "=" + field.getValue() + ",";
                        else
                            update_fields_value +=  field.getFieldname() + "='" + field.getValue() + "',";
                    }
                    map.put("id", id);
                    map.put("update_fields_value", update_fields_value.substring(0, update_fields_value.length() - 1));
                    res = dyndao.updateByPrimaryKey(map);
                } else {
                    //查询是否有相同流程数据
                    StringBuffer sql = new StringBuffer();
                    sql.append("SELECT * From ");
                    sql.append(list.get(0).getCformname() + list.get(0).getIver());
                    sql.append(" WHERE iflowId = " + flowId);
                    List<Map<String,Object>> mapList = dyndao.queryByFlowId(sql.toString());
                    if(mapList.size()>0){
                        return 0;
                    }
                    //执行添加操作
                    String field_names = "iformId,iflowId,", field_values = formId + ","+flowId+",";
                    for (AddFieldDto field : addList) {
                        field_names = field_names + field.getFieldname() + ",";
                        if (field.getType().equals("int") || field.getType().equals("float"))
                            field_values = field_values + field.getValue() + ",";
                        else
                            field_values = field_values + "'" + field.getValue() + "',";
                    }
                    map.clear();
                    map.put("table_name", list.get(0).getCformname() + list.get(0).getIver());
                    map.put("field_names", field_names.substring(0, field_names.length() - 1));
                    map.put("field_values", field_values.substring(0, field_values.length() - 1));
                    res = dyndao.insert(map);
                }
            } else if (list.get(0).getIcrttype() == 1) {
                //处理键值对
            } else {
                res = 0;
            }
        }
        return res;
    }

    @Override
    @Transactional
    public Map<String, Object> deleteFormContentByIds(Long formId, String ids) {
        Map<String, Object> resultMap = new HashMap<>();
        if (formId == null) {
            resultMap.put("result", 303);
            resultMap.put("msg", "formId为空");
            return resultMap;
        }
        if (!StringUtil.isNumeric(ids.replaceAll(",", ""))) {
            resultMap.put("result", 304);
            resultMap.put("msg", "ids格式错误");
            return resultMap;
        }
        DefForm defForm = new DefForm();
        defForm.setId(formId);
        List<DefForm> defFormList = dao.find(defForm);
        if (defFormList == null || defFormList.size() == 0) {
            resultMap.put("result", 305);
            resultMap.put("msg", "表单不存在");
            return resultMap;
        }
        defForm = defFormList.get(0);

        if (defForm.getIcrttype() == 0) {
            int count = 0;
            String[] idArray;
            if (ids.contains(",")) {
                idArray = ids.split(",");
            } else {
                idArray = new String[]{ids};
            }
            for (String idx : idArray) {
                Long id = new Long(idx);

                //判断是否是流程数据
                Map<String, Object> map = new HashMap<>();
                map.put("table_name", defForm.getCformname() + defForm.getIver());
                map.put("id", id);
                Map<String, Object> map1 = dyndao.queryById(map);
                if(StringUtil.isNotBlank(map1.get("iflowId"))){
                    //流程数据执行删除操作
                    Long fmfId = Long.parseLong(map1.get("iflowId").toString());
                    FlowMainFile o = new FlowMainFile();
                    o.setId(fmfId);
                    List<FlowMainFile> flowMainFileList = flowMainFileMapper.find(o);
                    if(flowMainFileList.size() == 1){
                        FlowMainFile flowMainFile = flowMainFileList.get(0);
                        if(flowMainFile.getBflag()){
                            resultMap.put("result", 306);
                            resultMap.put("msg", "办结无法删除");
                            return resultMap;
                        }
                        FlowMain flowMain = new FlowMain();
                        flowMain.setId(flowMainFile.getIfmid());
                        List<FlowMain> flowMainList = flowMainMapper.find(flowMain);
                        if(flowMainList.size()!=1){
                            resultMap.put("result", 307);
                            resultMap.put("msg", "流程定义表数据不存在");
                            return resultMap;
                        }
                        flowMain = flowMainList.get(0);
                        if(!(","+flowMain.getAdminId()+",").contains(","+TokenManager.getIdByKey()+",")  &&
                                !TokenManager.getUserNameByKey().equals(flowMainFile.getCcreator())){
                            resultMap.put("result", 308);
                            resultMap.put("msg", "当前用户无删除权限");
                            return resultMap;
                        }
                        StringBuffer sql = new StringBuffer();
                        sql.append("DELETE FROM ");
                        sql.append(flowMain.getCformident());
                        sql.append(" WHERE iflowId = " + o.getId());
                        flowMainFileMapper.deleteTableData(sql.toString());
                        FlowHistory flowHistory = new FlowHistory();
                        flowHistory.setIflid(o.getId());
                        flowHistoryMapper.delete(flowHistory);
                        WorkAttach workAttach = new WorkAttach();
                        workAttach.setIflid(o.getId());
                        deleteFiles(workAttach);
                        workAttachMapper.delete(workAttach);
                        flowMainFileMapper.delete(o);
                    }
                }

                count += dyndao.deleteByPrimaryKey(map);
            }
            resultMap.put("result", 1);
            resultMap.put("data", count);
        } else {
            //处理键值对
        }
        return resultMap;
    }

    private void deleteFiles(WorkAttach workAttach){
        List<WorkAttach> workAttachList = workAttachMapper.find(workAttach);
        if(workAttachList.size()>0){
            for (WorkAttach w: workAttachList) {
                String path = UtilPath.getRootPath() + w.getCpath() + w.getCfilename();
                File file = new File(path);
                if(file.exists() && file.isFile()){
                    file.delete();
                }
            }
        }
    }

    @Override
    @Transactional
    public Map<String, Object> getFields(Long formId) {
        Map<String, Object> resultMap = new HashMap<>();
        if (formId == null) {
            resultMap.put("res", 211);
            resultMap.put("msg", "formId为空");
            return resultMap;
        }
        DefForm defForm = new DefForm();
        defForm.setId(formId);
        List<DefForm> defFormList = dao.find(defForm);
        if (defFormList == null || defFormList.size() == 0) {
            resultMap.put("res", 212);
            resultMap.put("msg", "表单不存在");
            return resultMap;
        }
        defForm = defFormList.get(0);
        List<Object> list = new ArrayList<>();
        if (defForm.getIcrttype() == 0) {
            Map<String, Object> map = new HashMap<>();
            String dbname = dyndao.getCurDataBaseName();
            map.put("database_Name", dbname);
            map.put("table_name", defForm.getCformname() + defForm.getIver());
            String table_name = dyndao.isTargetTableExistInDB(map);
            if (table_name != null) {
//                List<Map<String, Object>> mapList = dyndao.findAll(StringUtil.getSysFiledsByPara(dbname, table_name, "COLUMN_NAME"));
//                for (Map<String, Object> map1 : mapList) {
//                    list.add((String) map1.get("COLUMN_NAME"));
//                }
                list.add(keydao.queryFieldsByFormId(formId));
            }
        } else {
            Map<String, Object> para = new HashMap<>();
            para.put("search_sql", " and iformId=" + formId);
            para.put("field_names", "cfieldName");
            para.put("table_name", "def_field");
            List<Map<String, Object>> mapList = dyndao.findAll(para);
            for (Map<String, Object> map1 : mapList) {
                list.add((String) map1.get("cfieldName"));
            }
        }
        resultMap.put("res", 1);
        resultMap.put("data", list);
        return resultMap;
    }

    private String fieldSQL(DataTypeDto field) {
        String plugins = field.getPlugins();
        if (plugins.equalsIgnoreCase("textarea")
                || plugins.equalsIgnoreCase("listctrl")) {
            return " TEXT";
        } else if (plugins.equalsIgnoreCase("text")) {
            String type = field.getType();
            if ("text".equals(type)) {
                return " VARCHAR(255) NOT NULL DEFAULT ''";
            } else if ("int".equals(type)) {
                return " INT NOT NULL DEFAULT 0";
            } else if ("float".equals(type)) {
                return " FLOAT ";
            } else {
                return " VARCHAR(255) NOT NULL DEFAULT ''";
            }
        } else if (plugins.equalsIgnoreCase("radios")) {
            return " VARCHAR(255) NOT NULL DEFAULT ''";
        } else {
            return " VARCHAR(255) NOT NULL DEFAULT ''";
        }
    }

    @Override
    public int showOrHide(RunKeyFormDto o) {
        if (!StringUtil.isNotBlank(o.getId())){
            return 201;
        }
        if (!StringUtil.isNotBlank(o.getIsShowOnTel())){
            return 202;
        }
        return keydao.showOrHide(o);
    }

}
